package com.hexingmo.dawn.lang;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.spi.FileSystemProvider;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * 磁盘工具类
 * <p>
 * 提供常用的磁盘操作工具方法，帮助程序员更高效地完成开发。
 * 包括文件操作、目录操作、磁盘信息、文件监控等功能。
 * <p>
 * 使用示例：
 * // 检查磁盘空间
 * if (DeskUtils.hasEnoughSpace("/path/to/dir", 1024 * 1024 * 100)) {
 * System.out.println("磁盘空间充足");
 * }
 * <p>
 * // 复制目录
 * DeskUtils.copyDirectory("/source", "/target");
 *
 * @author He Xing Mo
 * @since 1.0
 */
public class DeskUtils {

    private DeskUtils() {
        throw new IllegalStateException("Static utility classes do not support instantiation");
    }

    // ==================== 磁盘空间相关 ====================


    /**
     * 检查磁盘空间是否充足（以MB为单位）
     *
     * @param path            检查路径
     * @param requiredSpaceMB 需要的空间大小（MB）
     * @return 如果可用空间大于等于需要的空间返回true，否则返回false
     */
    public static boolean hasEnoughSpaceMB(String path, long requiredSpaceMB) {
        return hasEnoughSpace(path, requiredSpaceMB * 1024 * 1024);
    }

    /**
     * 检查磁盘空间是否充足（以GB为单位）
     *
     * @param path            检查路径
     * @param requiredSpaceGB 需要的空间大小（GB）
     * @return 如果可用空间大于等于需要的空间返回true，否则返回false
     */
    public static boolean hasEnoughSpaceGB(String path, long requiredSpaceGB) {
        return hasEnoughSpace(path, requiredSpaceGB * 1024 * 1024 * 1024);
    }

    /**
     * 检查指定路径是否有足够的磁盘空间
     * 使用 {@link java.nio.file.FileStore#getUsableSpace()} 方法获取可用空间。
     * 相比 {@link java.io.File#getFreeSpace()}，getUsableSpace() 更准确，
     * 因为它考虑了用户权限和磁盘配额限制。
     *
     * <h3>空间概念详解：</h3>
     * <ul>
     *   <li><strong>Total Space</strong>：文件系统的总容量，包括所有已分配和未分配的空间</li>
     *   <li><strong>Usable Space</strong>：当前用户实际可用的空间（考虑权限和配额）</li>
     *   <li><strong>Free Space</strong>：文件系统中未被分配的空间</li>
     *   <li><strong>Unallocated Space</strong>：未分配给任何文件的空间</li>
     * </ul>
     *
     * <h3>API选择说明：</h3>
     * <table border="1">
     *   <tr><th>方法</th><th>返回内容</th><th>考虑因素</th><th>适用场景</th></tr>
     *   <tr><td>File.getFreeSpace()</td><td>物理空闲空间</td><td>不考虑权限和配额</td><td>简单空间检查</td></tr>
     *   <tr><td>FileStore.getUsableSpace()</td><td>实际可用空间</td><td>考虑权限和配额</td><td>精确空间检查</td></tr>
     * </table>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>文件上传</strong>：上传前检查目标目录空间是否充足</li>
     *   <li><strong>数据库备份</strong>：备份前验证备份目录空间</li>
     *   <li><strong>日志文件</strong>：写入日志前检查磁盘空间</li>
     *   <li><strong>临时文件</strong>：创建临时文件前检查空间</li>
     *   <li><strong>缓存清理</strong>：根据可用空间决定清理策略</li>
     * </ul>
     *
     * <h3>性能考虑：</h3>
     * <ul>
     *   <li>此操作是轻量级的，不会影响系统性能</li>
     *   <li>建议在关键操作前调用，避免操作失败</li>
     *   <li>对于频繁检查的场景，可以考虑缓存结果</li>
     * </ul>
     *
     * <h3>跨平台兼容性：</h3>
     * <ul>
     *   <li><strong>Windows</strong>：支持NTFS、FAT32等文件系统</li>
     *   <li><strong>Linux</strong>：支持ext4、xfs、btrfs等文件系统</li>
     *   <li><strong>macOS</strong>：支持APFS、HFS+等文件系统</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 检查是否有100MB可用空间
     * if (DeskUtils.hasEnoughSpace("/uploads", 100 * 1024 * 1024)) {
     *     System.out.println("空间充足，可以上传文件");
     * } else {
     *     System.out.println("空间不足，需要清理磁盘");
     * }
     *
     * // 检查数据库备份空间
     * long backupSize = 1024 * 1024 * 1024; // 1GB
     * if (DeskUtils.hasEnoughSpace("/backup", backupSize)) {
     *     performDatabaseBackup();
     * } else {
     *     sendAlert("备份空间不足");
     * }
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>在多用户环境中，可用空间可能随时变化</li>
     *   <li>某些文件系统可能有保留空间，实际可用空间可能小于显示值</li>
     *   <li>网络文件系统的空间检查可能较慢</li>
     *   <li>建议在关键操作前重新检查空间</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #hasEnoughSpaceMB(String, long)} - 以MB为单位检查空间</li>
     *   <li>{@link #hasEnoughSpaceGB(String, long)} - 以GB为单位检查空间</li>
     *   <li>{@link #getDiskUsagePercentage(String)} - 获取磁盘使用率</li>
     *   <li>{@link #getSpecificDiskUsableSpace(String)} - 获取具体可用空间</li>
     * </ul>
     *
     * @param path          检查路径，可以是文件或目录路径
     * @param requiredSpace 需要的空间大小（字节）
     * @return 如果可用空间大于等于需要的空间返回true，否则返回false
     * @see java.nio.file.FileStore#getUsableSpace()
     * @see java.io.File#getFreeSpace()
     * @see #getSpecificDiskUsableSpace(String)
     */
    public static boolean hasEnoughSpace(String path, long requiredSpace) {
        try {
            return getSpecificDiskUsableSpace(path) >= requiredSpace;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取磁盘使用率
     *
     * <h3>技术原理：</h3>
     * 使用 {@link java.io.File} API 获取磁盘空间信息，通过计算已使用空间与总空间的比值
     * 来得到磁盘使用率。计算公式：使用率 = (总空间 - 空闲空间) / 总空间 × 100%
     *
     * <h3>空间概念详解：</h3>
     * <ul>
     *   <li><strong>Total Space</strong>：文件系统的总容量，包括所有已分配和未分配的空间</li>
     *   <li><strong>Free Space</strong>：文件系统中未被分配的空间</li>
     *   <li><strong>Used Space</strong>：已使用的空间 = 总空间 - 空闲空间</li>
     *   <li><strong>Usage Percentage</strong>：使用率 = 已使用空间 / 总空间 × 100%</li>
     * </ul>
     *
     * <h3>API选择说明：</h3>
     * 使用传统的 {@link java.io.File} API 而不是 NIO.2 API，原因如下：
     * <ul>
     *   <li><strong>兼容性更好</strong>：在所有Java版本中都能正常工作</li>
     *   <li><strong>稳定性更高</strong>：在某些特殊环境下更稳定</li>
     *   <li><strong>计算简单</strong>：直接使用总空间和空闲空间计算</li>
     * </ul>
     *
     * <h3>使用率参考标准：</h3>
     * <table border="1">
     *   <tr><th>使用率范围</th><th>状态</th><th>建议操作</th></tr>
     *   <tr><td>0-70%</td><td>正常</td><td>无需操作</td></tr>
     *   <tr><td>70-85%</td><td>需要注意</td><td>考虑清理不必要的文件</td></tr>
     *   <tr><td>85-95%</td><td>警告</td><td>立即清理，避免系统性能下降</td></tr>
     *   <tr><td>95%+</td><td>危险</td><td>紧急清理，可能影响系统稳定性</td></tr>
     * </table>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>系统监控</strong>：定期检查磁盘使用情况</li>
     *   <li><strong>存储管理</strong>：评估存储空间需求</li>
     *   <li><strong>性能优化</strong>：磁盘空间不足时优化性能</li>
     *   <li><strong>备份策略</strong>：根据使用率制定备份计划</li>
     *   <li><strong>告警系统</strong>：设置磁盘使用率告警阈值</li>
     * </ul>
     *
     * <h3>性能考虑：</h3>
     * <ul>
     *   <li>此操作是轻量级的，不会影响系统性能</li>
     *   <li>建议在非高峰期进行监控</li>
     *   <li>对于频繁监控的场景，可以考虑缓存结果</li>
     *   <li>网络文件系统的检查可能较慢</li>
     * </ul>
     *
     * <h3>跨平台兼容性：</h3>
     * <ul>
     *   <li><strong>Windows</strong>：支持NTFS、FAT32等文件系统</li>
     *   <li><strong>Linux</strong>：支持ext4、xfs、btrfs等文件系统</li>
     *   <li><strong>macOS</strong>：支持APFS、HFS+等文件系统</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 检查磁盘使用率
     * double usage = DeskUtils.getDiskUsagePercentage("/");
     * if (usage > 85) {
     *     System.out.println("磁盘使用率过高: " + usage + "%");
     *     // 执行清理操作
     *     cleanupDisk();
     * } else {
     *     System.out.println("磁盘使用率正常: " + usage + "%");
     * }
     *
     * // 监控多个磁盘
     * String[] disks = {"/", "/home", "/var"};
     * for (String disk : disks) {
     *     double usage = DeskUtils.getDiskUsagePercentage(disk);
     *     System.out.println(disk + " 使用率: " + usage + "%");
     * }
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>某些文件系统可能有保留空间，实际可用空间可能小于计算值</li>
     *   <li>在多用户环境中，使用率可能随时变化</li>
     *   <li>网络文件系统的使用率计算可能不准确</li>
     *   <li>建议结合其他指标（如IOPS、响应时间）综合评估</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #getSpecificDiskUsagePercentage(String)} - 使用NIO.2 API获取使用率</li>
     *   <li>{@link #getDiskTotalSpace(String)} - 获取磁盘总空间</li>
     *   <li>{@link #getDiskFreeSpace(String)} - 获取磁盘空闲空间</li>
     *   <li>{@link #getDiskUsedSpace(String)} - 获取磁盘已使用空间</li>
     *   <li>{@link #formatBytes(long)} - 格式化字节显示</li>
     * </ul>
     *
     * <h3>技术细节：</h3>
     * <ul>
     *   <li>使用 {@link java.io.File#getTotalSpace()} 获取总空间</li>
     *   <li>使用 {@link java.io.File#getFreeSpace()} 获取空闲空间</li>
     *   <li>通过减法计算已使用空间</li>
     *   <li>使用浮点数除法确保精度</li>
     *   <li>乘以100转换为百分比</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @return 磁盘使用率（0-100），如果获取失败返回-1
     * @see java.io.File#getTotalSpace()
     * @see java.io.File#getFreeSpace()
     * @see #getSpecificDiskUsagePercentage(String)
     * @see #getDiskTotalSpace(String)
     * @see #getDiskFreeSpace(String)
     */
    public static double getDiskUsagePercentage(String path) {
        try {
            File file = new File(path);
            long totalSpace = file.getTotalSpace();
            long freeSpace = file.getFreeSpace();
            long usedSpace = totalSpace - freeSpace;
            return totalSpace > 0 ? (double) usedSpace / totalSpace * 100 : 0;
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 使用NIO.2 API获取磁盘使用率
     *
     * <h3>技术原理：</h3>
     * 使用 {@link java.nio.file.FileStore} API 获取磁盘空间信息，通过计算未分配空间与总空间的比值
     * 来得到磁盘使用率。计算公式：使用率 = 未分配空间 / 总空间 × 100%
     *
     * <h3>与File API的区别：</h3>
     * <table border="1">
     *   <tr><th>特性</th><th>File API</th><th>FileStore API</th></tr>
     *   <tr><td>空间计算</td><td>总空间 - 空闲空间</td><td>未分配空间</td></tr>
     *   <tr><td>权限考虑</td><td>不考虑用户权限</td><td>考虑用户权限和配额</td></tr>
     *   <tr><td>精确度</td><td>基础精度</td><td>更高精度</td></tr>
     *   <tr><td>兼容性</td><td>所有Java版本</td><td>Java 7+</td></tr>
     *   <tr><td>性能</td><td>较快</td><td>相对较慢</td></tr>
     * </table>
     *
     * <h3>空间概念详解：</h3>
     * <ul>
     *   <li><strong>Total Space</strong>：文件系统的总容量，包括所有已分配和未分配的空间</li>
     *   <li><strong>Unallocated Space</strong>：未分配给任何文件的空间，这是更准确的使用率计算基础</li>
     *   <li><strong>Used Space</strong>：已使用的空间 = 总空间 - 未分配空间</li>
     *   <li><strong>Usage Percentage</strong>：使用率 = 未分配空间 / 总空间 × 100%</li>
     * </ul>
     *
     * <h3>API选择说明：</h3>
     * 使用 {@link java.nio.file.FileStore} API 而不是传统的 {@link java.io.File} API，原因如下：
     * <ul>
     *   <li><strong>更精确</strong>：使用未分配空间计算，更准确反映实际使用情况</li>
     *   <li><strong>权限感知</strong>：考虑用户权限和磁盘配额限制</li>
     *   <li><strong>现代API</strong>：使用Java 7引入的NIO.2 API</li>
     *   <li><strong>功能丰富</strong>：提供更多文件系统信息</li>
     * </ul>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>精确监控</strong>：需要高精度磁盘使用率监控</li>
     *   <li><strong>多用户环境</strong>：考虑用户权限和配额限制</li>
     *   <li><strong>企业级应用</strong>：需要更准确的存储管理</li>
     *   <li><strong>云环境</strong>：在云存储环境中使用</li>
     *   <li><strong>虚拟化环境</strong>：在虚拟机中监控磁盘使用</li>
     * </ul>
     *
     * <h3>性能考虑：</h3>
     * <ul>
     *   <li>此操作比File API稍慢，但提供更准确的结果</li>
     *   <li>建议在需要精确度时使用，一般监控可使用File API</li>
     *   <li>对于频繁检查的场景，可以考虑缓存结果</li>
     *   <li>网络文件系统的检查可能较慢</li>
     * </ul>
     *
     * <h3>跨平台兼容性：</h3>
     * <ul>
     *   <li><strong>Windows</strong>：支持NTFS、FAT32等文件系统</li>
     *   <li><strong>Linux</strong>：支持ext4、xfs、btrfs等文件系统</li>
     *   <li><strong>macOS</strong>：支持APFS、HFS+等文件系统</li>
     *   <li><strong>网络文件系统</strong>：支持NFS、SMB等</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 获取精确的磁盘使用率
     * double usage = DeskUtils.getSpecificDiskUsagePercentage("/");
     * System.out.println("精确磁盘使用率: " + usage + "%");
     *
     * // 比较两种API的结果
     * double fileUsage = DeskUtils.getDiskUsagePercentage("/");
     * double storeUsage = DeskUtils.getSpecificDiskUsagePercentage("/");
     * System.out.println("File API使用率: " + fileUsage + "%");
     * System.out.println("FileStore API使用率: " + storeUsage + "%");
     *
     * // 在多用户环境中使用
     * if (DeskUtils.getSpecificDiskUsagePercentage("/home") > 85) {
     *     System.out.println("用户目录空间不足");
     *     checkUserQuotas();
     * }
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>需要Java 7或更高版本</li>
     *   <li>在某些特殊文件系统上可能不可用</li>
     *   <li>结果可能与File API略有不同</li>
     *   <li>建议在关键应用中使用此方法</li>
     *   <li>网络文件系统的结果可能不准确</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #getDiskUsagePercentage(String)} - 使用File API获取使用率</li>
     *   <li>{@link #getSpecificDiskTotalSpace(String)} - 获取FileStore总空间</li>
     *   <li>{@link #getSpecificDiskUnallocatedSpace(String)} - 获取未分配空间</li>
     *   <li>{@link #getSpecificDiskUsableSpace(String)} - 获取可用空间</li>
     * </ul>
     *
     * <h3>技术细节：</h3>
     * <ul>
     *   <li>使用 {@link java.nio.file.FileStore#getTotalSpace()} 获取总空间</li>
     *   <li>使用 {@link java.nio.file.FileStore#getUnallocatedSpace()} 获取未分配空间</li>
     *   <li>通过 {@link #getFileStore(String)} 获取FileStore对象</li>
     *   <li>使用浮点数除法确保精度</li>
     *   <li>乘以100转换为百分比</li>
     * </ul>
     *
     * <h3>错误处理：</h3>
     * <ul>
     *   <li>如果获取FileStore失败，返回-1</li>
     *   <li>如果总空间为0，返回0</li>
     *   <li>捕获所有异常并返回-1</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @return 磁盘使用率（0-100），如果获取失败返回-1
     *
     * @see java.nio.file.FileStore#getTotalSpace()
     * @see java.nio.file.FileStore#getUnallocatedSpace()
     * @see #getDiskUsagePercentage(String)
     * @see #getSpecificDiskTotalSpace(String)
     * @see #getSpecificDiskUnallocatedSpace(String)
     */
    public static double getSpecificDiskUsagePercentage(String path) {
        try {
            long totalSpace = getSpecificDiskTotalSpace(path);
            long unallocatedSpace = getSpecificDiskUsableSpace(path);
            long usedSpace = totalSpace - unallocatedSpace;
            return totalSpace > 0 ? (double) usedSpace / totalSpace * 100 : 0;
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 判断磁盘使用率是否高于指定阈值
     *
     * <h3>技术原理：</h3>
     * 通过调用 {@link #getSpecificDiskUsagePercentage(String)} 获取当前磁盘使用率，
     * 然后与指定的阈值进行比较。当使用率超过阈值时返回true，表示需要关注。
     *
     * <h3>阈值参考标准：</h3>
     * <table border="1">
     *   <tr><th>阈值范围</th><th>状态</th><th>建议操作</th></tr>
     *   <tr><td>70%</td><td>需要注意</td><td>考虑清理不必要的文件</td></tr>
     *   <tr><td>85%</td><td>警告</td><td>立即清理，避免系统性能下降</td></tr>
     *   <tr><td>95%</td><td>危险</td><td>紧急清理，可能影响系统稳定性</td></tr>
     * </table>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>监控告警</strong>：设置自动告警阈值</li>
     *   <li><strong>自动清理</strong>：触发自动清理任务</li>
     *   <li><strong>备份策略</strong>：根据使用率调整备份频率</li>
     *   <li><strong>性能优化</strong>：在空间不足时优化性能</li>
     *   <li><strong>资源管理</strong>：动态调整资源分配</li>
     * </ul>
     *
     * <h3>性能考虑：</h3>
     * <ul>
     *   <li>此操作会调用磁盘空间检查，建议合理设置检查频率</li>
     *   <li>对于频繁检查的场景，可以考虑缓存结果</li>
     *   <li>建议在非高峰期进行监控</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 检查磁盘使用率是否超过85%
     * if (DeskUtils.isDiskUsageAbove("/", 85.0)) {
     *     System.out.println("磁盘使用率过高，需要清理");
     *     performDiskCleanup();
     * } else {
     *     System.out.println("磁盘使用率正常");
     * }
     *
     * // 多级告警系统
     * if (DeskUtils.isDiskUsageAbove("/", 95.0)) {
     *     sendEmergencyAlert("磁盘空间严重不足");
     * } else if (DeskUtils.isDiskUsageAbove("/", 85.0)) {
     *     sendWarningAlert("磁盘空间不足");
     * } else if (DeskUtils.isDiskUsageAbove("/", 70.0)) {
     *     sendInfoAlert("磁盘空间需要注意");
     * }
     *
     * // 自动清理策略
     * if (DeskUtils.isDiskUsageAbove("/var/log", 80.0)) {
     *     cleanupOldLogs();
     * }
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>阈值设置过高可能导致系统性能问题</li>
     *   <li>阈值设置过低可能产生过多告警</li>
     *   <li>建议根据实际业务需求调整阈值</li>
     *   <li>不同磁盘分区可能需要不同的阈值</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #isDiskUsageBelow(String, double)} - 检查使用率是否低于阈值</li>
     *   <li>{@link #getSpecificDiskUsagePercentage(String)} - 获取磁盘使用率</li>
     *   <li>{@link #hasEnoughSpace(String, long)} - 检查是否有足够空间</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @param threshold 阈值（百分比，0-100）
     * @return 如果使用率高于阈值返回true，否则返回false
     *
     * @see #getDiskUsagePercentage(String)
     * @see #isDiskUsageBelow(String, double)
     */
    public static boolean isDiskUsageAbove(String path, double threshold) {
        try {
            double usage = getSpecificDiskUsagePercentage(path);
            return usage > 0 && usage >= threshold;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断磁盘使用率是否低于指定阈值
     *
     * <h3>技术原理：</h3>
     * 通过调用 {@link #getSpecificDiskUsagePercentage(String)} 获取当前磁盘使用率，
     * 然后与指定的阈值进行比较。当使用率低于阈值时返回true，表示空间充足。
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>空间充足检查</strong>：确认磁盘空间充足</li>
     *   <li><strong>安全阈值</strong>：确保有足够的缓冲空间</li>
     *   <li><strong>性能优化</strong>：在空间充足时进行优化操作</li>
     *   <li><strong>备份验证</strong>：确认有足够空间进行备份</li>
     *   <li><strong>部署检查</strong>：部署前检查目标磁盘空间</li>
     * </ul>
     *
     * <h3>安全阈值建议：</h3>
     * <ul>
     *   <li><strong>系统盘</strong>：建议保持30%以下</li>
     *   <li><strong>数据盘</strong>：建议保持50%以下</li>
     *   <li><strong>日志盘</strong>：建议保持70%以下</li>
     *   <li><strong>临时盘</strong>：建议保持80%以下</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 检查磁盘使用率是否低于30%（安全阈值）
     * if (DeskUtils.isDiskUsageBelow("/", 30.0)) {
     *     System.out.println("磁盘空间充足，可以安全操作");
     *     performSafeOperation();
     * } else {
     *     System.out.println("磁盘空间不足，需要清理");
     * }
     *
     * // 部署前检查
     * if (DeskUtils.isDiskUsageBelow("/opt", 50.0)) {
     *     deployApplication();
     * } else {
     *     throw new InsufficientSpaceException("部署空间不足");
     * }
     *
     * // 备份前验证
     * if (DeskUtils.isDiskUsageBelow("/backup", 70.0)) {
     *     performBackup();
     * } else {
     *     sendAlert("备份空间不足");
     * }
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>阈值设置过低可能导致空间浪费</li>
     *   <li>阈值设置过高可能影响系统性能</li>
     *   <li>建议根据磁盘类型和用途设置不同阈值</li>
     *   <li>定期评估和调整阈值设置</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #isDiskUsageAbove(String, double)} - 检查使用率是否高于阈值</li>
     *   <li>{@link #getSpecificDiskUsagePercentage(String)} - 获取磁盘使用率</li>
     *   <li>{@link #hasEnoughSpace(String, long)} - 检查是否有足够空间</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @param threshold 阈值（百分比，0-100）
     * @return 如果使用率低于阈值返回true，否则返回false
     *
     * @see #getDiskUsagePercentage(String)
     * @see #isDiskUsageAbove(String, double)
     */
    public static boolean isDiskUsageBelow(String path, double threshold) {
        try {
            double usage = getSpecificDiskUsagePercentage(path);
            return usage > 0 && usage < threshold;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断磁盘使用率是否在指定范围内
     *
     * <h3>技术原理：</h3>
     * 通过调用 {@link #getSpecificDiskUsagePercentage(String)} 获取当前磁盘使用率，
     * 然后检查是否在指定的最小值和最大值范围内。
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>健康检查</strong>：确保磁盘使用率在合理范围内</li>
     *   <li><strong>性能优化</strong>：在最佳使用率范围内运行</li>
     *   <li><strong>容量规划</strong>：监控磁盘使用趋势</li>
     *   <li><strong>告警管理</strong>：设置多级告警阈值</li>
     *   <li><strong>资源调度</strong>：根据使用率调度任务</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 检查磁盘使用率是否在30%-70%的健康范围内
     * if (DeskUtils.isDiskUsageInRange("/", 30.0, 70.0)) {
     *     System.out.println("磁盘使用率健康");
     * } else {
     *     System.out.println("磁盘使用率异常");
     * }
     *
     * // 多级监控
     * if (DeskUtils.isDiskUsageInRange("/", 0.0, 30.0)) {
     *     System.out.println("磁盘空间充足");
     * } else if (DeskUtils.isDiskUsageInRange("/", 30.0, 70.0)) {
     *     System.out.println("磁盘使用率正常");
     * } else if (DeskUtils.isDiskUsageInRange("/", 70.0, 85.0)) {
     *     System.out.println("磁盘使用率较高");
     * } else {
     *     System.out.println("磁盘使用率过高");
     * }
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>确保最小值小于最大值</li>
     *   <li>范围设置要符合实际业务需求</li>
     *   <li>建议设置合理的缓冲区</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #isDiskUsageAbove(String, double)} - 检查使用率是否高于阈值</li>
     *   <li>{@link #isDiskUsageBelow(String, double)} - 检查使用率是否低于阈值</li>
     *   <li>{@link #getDiskUsagePercentage(String)} - 获取磁盘使用率</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @param minThreshold 最小阈值（百分比，0-100）
     * @param maxThreshold 最大阈值（百分比，0-100）
     * @return 如果使用率在指定范围内返回true，否则返回false
     *
     * @see #getDiskUsagePercentage(String)
     * @see #isDiskUsageAbove(String, double)
     * @see #isDiskUsageBelow(String, double)
     */
    public static boolean isDiskUsageInRange(String path, double minThreshold, double maxThreshold) {
        try {
            double usage = getDiskUsagePercentage(path);
            return usage > 0 && usage >= minThreshold && usage <= maxThreshold;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取磁盘总空间
     *
     * <h3>技术原理：</h3>
     * 使用 {@link java.io.File#getTotalSpace()} 方法获取文件系统的总容量。
     * 总空间包括所有已分配和未分配的空间，是文件系统的物理容量。
     *
     * <h3>空间概念详解：</h3>
     * <ul>
     *   <li><strong>Total Space</strong>：文件系统的总容量，包括所有已分配和未分配的空间</li>
     *   <li><strong>Physical Capacity</strong>：物理磁盘的实际容量</li>
     *   <li><strong>File System Overhead</strong>：文件系统元数据占用的空间</li>
     *   <li><strong>Reserved Space</strong>：系统保留的空间</li>
     * </ul>
     *
     * <h3>API特点：</h3>
     * <ul>
     *   <li><strong>兼容性好</strong>：在所有Java版本中都能正常工作</li>
     *   <li><strong>性能稳定</strong>：轻量级操作，不会影响系统性能</li>
     *   <li><strong>结果准确</strong>：直接获取文件系统报告的总空间</li>
     *   <li><strong>异常安全</strong>：捕获所有异常并返回-1</li>
     * </ul>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>容量规划</strong>：了解磁盘总容量</li>
     *   <li><strong>存储管理</strong>：评估存储需求</li>
     *   <li><strong>系统监控</strong>：监控磁盘容量变化</li>
     *   <li><strong>备份策略</strong>：制定备份计划</li>
     *   <li><strong>性能分析</strong>：分析磁盘使用情况</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 获取磁盘总空间
     * long totalSpace = DeskUtils.getDiskTotalSpace("/");
     * System.out.println("磁盘总空间: " + DeskUtils.formatBytes(totalSpace));
     *
     * // 计算可用空间比例
     * long freeSpace = DeskUtils.getDiskFreeSpace("/");
     * double freePercentage = (double) freeSpace / totalSpace * 100;
     * System.out.println("可用空间比例: " + freePercentage + "%");
     *
     * // 监控多个磁盘
     * String[] disks = {"/", "/home", "/var"};
     * for (String disk : disks) {
     *     long space = DeskUtils.getDiskTotalSpace(disk);
     *     System.out.println(disk + " 总空间: " + DeskUtils.formatBytes(space));
     * }
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>总空间可能因文件系统类型而异</li>
     *   <li>某些文件系统可能有隐藏的保留空间</li>
     *   <li>网络文件系统的总空间可能不准确</li>
     *   <li>建议结合其他指标综合评估</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #getSpecificDiskTotalSpace(String)} - 使用NIO.2 API获取总空间</li>
     *   <li>{@link #getDiskFreeSpace(String)} - 获取空闲空间</li>
     *   <li>{@link #getDiskUsedSpace(String)} - 获取已使用空间</li>
     *   <li>{@link #formatBytes(long)} - 格式化字节显示</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @return 磁盘总空间（字节），如果获取失败返回-1
     *
     * @see java.io.File#getTotalSpace()
     * @see #getSpecificDiskTotalSpace(String)
     * @see #getDiskFreeSpace(String)
     * @see #getDiskUsedSpace(String)
     */
    public static long getDiskTotalSpace(String path) {
        try {
            File file = new File(path);
            return file.getTotalSpace();
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 获取磁盘已使用空间
     *
     * <h3>技术原理：</h3>
     * 通过计算总空间与空闲空间的差值来获取已使用空间。
     * 计算公式：已使用空间 = 总空间 - 空闲空间
     *
     * <h3>空间概念详解：</h3>
     * <ul>
     *   <li><strong>Used Space</strong>：已分配给文件的空间</li>
     *   <li><strong>File Data</strong>：实际文件内容占用的空间</li>
     *   <li><strong>File System Metadata</strong>：文件系统元数据占用的空间</li>
     *   <li><strong>Directory Entries</strong>：目录项占用的空间</li>
     * </ul>
     *
     * <h3>计算方式：</h3>
     * <ul>
     *   <li><strong>间接计算</strong>：通过总空间减去空闲空间得到</li>
     *   <li><strong>实时性</strong>：每次调用都会重新计算</li>
     *   <li><strong>准确性</strong>：基于文件系统报告的数据</li>
     * </ul>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>存储分析</strong>：分析磁盘使用情况</li>
     *   <li><strong>容量监控</strong>：监控磁盘使用趋势</li>
     *   <li><strong>清理决策</strong>：决定是否需要清理</li>
     *   <li><strong>性能优化</strong>：优化磁盘性能</li>
     *   <li><strong>告警系统</strong>：设置使用率告警</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 获取磁盘已使用空间
     * long usedSpace = DeskUtils.getDiskUsedSpace("/");
     * System.out.println("已使用空间: " + DeskUtils.formatBytes(usedSpace));
     *
     * // 计算使用率
     * long totalSpace = DeskUtils.getDiskTotalSpace("/");
     * double usagePercentage = (double) usedSpace / totalSpace * 100;
     * System.out.println("使用率: " + usagePercentage + "%");
     *
     * // 监控使用趋势
     * long currentUsed = DeskUtils.getDiskUsedSpace("/");
     * long previousUsed = getPreviousUsedSpace(); // 假设的方法
     * long growth = currentUsed - previousUsed;
     * System.out.println("空间增长: " + DeskUtils.formatBytes(growth));
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>已使用空间包括文件系统元数据</li>
     *   <li>某些文件系统可能有压缩或去重功能</li>
     *   <li>网络文件系统的计算可能不准确</li>
     *   <li>建议定期监控使用趋势</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #getDiskTotalSpace(String)} - 获取总空间</li>
     *   <li>{@link #getDiskFreeSpace(String)} - 获取空闲空间</li>
     *   <li>{@link #getDiskUsagePercentage(String)} - 获取使用率</li>
     *   <li>{@link #formatBytes(long)} - 格式化字节显示</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @return 磁盘已使用空间（字节），如果获取失败返回-1
     *
     * @see java.io.File#getTotalSpace()
     * @see java.io.File#getFreeSpace()
     * @see #getDiskTotalSpace(String)
     * @see #getDiskFreeSpace(String)
     */
    public static long getDiskUsedSpace(String path) {
        try {
            File file = new File(path);
            long totalSpace = file.getTotalSpace();
            long freeSpace = file.getFreeSpace();
            return totalSpace - freeSpace;
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 获取磁盘空闲空间
     *
     * <h3>技术原理：</h3>
     * 使用 {@link java.io.File#getFreeSpace()} 方法获取文件系统中未被分配的空间。
     * 空闲空间是当前可以立即使用的空间。
     *
     * <h3>空间概念详解：</h3>
     * <ul>
     *   <li><strong>Free Space</strong>：文件系统中未被分配的空间</li>
     *   <li><strong>Immediately Available</strong>：可以立即使用的空间</li>
     *   <li><strong>File System Level</strong>：文件系统层面的空闲空间</li>
     *   <li><strong>Not Reserved</strong>：不包括系统保留的空间</li>
     * </ul>
     *
     * <h3>与可用空间的区别：</h3>
     * <table border="1">
     *   <tr><th>特性</th><th>Free Space</th><th>Usable Space</th></tr>
     *   <tr><td>定义</td><td>未被分配的空间</td><td>用户实际可用的空间</td></tr>
     *   <tr><td>权限考虑</td><td>不考虑用户权限</td><td>考虑用户权限和配额</td></tr>
     *   <tr><td>精确度</td><td>基础精度</td><td>更高精度</td></tr>
     *   <tr><td>API</td><td>File API</td><td>FileStore API</td></tr>
     * </table>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>空间检查</strong>：检查是否有足够空间</li>
     *   <li><strong>文件操作</strong>：写入文件前检查空间</li>
     *   <li><strong>备份验证</strong>：备份前验证空间</li>
     *   <li><strong>系统监控</strong>：监控磁盘空间变化</li>
     *   <li><strong>告警系统</strong>：设置空间告警</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 获取磁盘空闲空间
     * long freeSpace = DeskUtils.getDiskFreeSpace("/");
     * System.out.println("空闲空间: " + DeskUtils.formatBytes(freeSpace));
     *
     * // 检查是否有足够空间
     * long requiredSpace = 1024 * 1024 * 1024; // 1GB
     * if (freeSpace >= requiredSpace) {
     *     System.out.println("空间充足，可以执行操作");
     * } else {
     *     System.out.println("空间不足，需要清理");
     * }
     *
     * // 监控空间变化
     * long currentFree = DeskUtils.getDiskFreeSpace("/");
     * long previousFree = getPreviousFreeSpace(); // 假设的方法
     * long change = currentFree - previousFree;
     * System.out.println("空间变化: " + DeskUtils.formatBytes(change));
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>空闲空间不包括系统保留空间</li>
     *   <li>某些文件系统可能有压缩功能</li>
     *   <li>网络文件系统的空闲空间可能不准确</li>
     *   <li>建议结合可用空间一起评估</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #getSpecificDiskUsableSpace(String)} - 获取可用空间</li>
     *   <li>{@link #getDiskTotalSpace(String)} - 获取总空间</li>
     *   <li>{@link #getDiskUsedSpace(String)} - 获取已使用空间</li>
     *   <li>{@link #hasEnoughSpace(String, long)} - 检查空间是否充足</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @return 磁盘空闲空间（字节），如果获取失败返回-1
     *
     * @see java.io.File#getFreeSpace()
     * @see #getSpecificDiskUsableSpace(String)
     * @see #getDiskTotalSpace(String)
     * @see #getDiskUsedSpace(String)
     */
    public static long getDiskFreeSpace(String path) {
        try {
            File file = new File(path);
            return file.getFreeSpace();
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 使用NIO.2 API获取磁盘总空间
     *
     * <h3>技术原理：</h3>
     * 使用 {@link java.nio.file.FileStore#getTotalSpace()} 方法获取文件系统的总容量。
     * 这是NIO.2 API提供的更现代的空间获取方式。
     *
     * <h3>与File API的区别：</h3>
     * <table border="1">
     *   <tr><th>特性</th><th>File API</th><th>FileStore API</th></tr>
     *   <tr><td>API版本</td><td>Java 1.2+</td><td>Java 7+</td></tr>
     *   <tr><td>功能丰富度</td><td>基础功能</td><td>更多功能</td></tr>
     *   <tr><td>性能</td><td>较快</td><td>相对较慢</td></tr>
     *   <tr><td>精确度</td><td>基础精度</td><td>更高精度</td></tr>
     * </table>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>现代应用</strong>：使用Java 7+的应用</li>
     *   <li><strong>精确监控</strong>：需要高精度空间信息</li>
     *   <li><strong>企业级应用</strong>：需要更可靠的空间管理</li>
     *   <li><strong>云环境</strong>：在云存储环境中使用</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 获取精确的磁盘总空间
     * long totalSpace = DeskUtils.getSpecificDiskTotalSpace("/");
     * System.out.println("精确总空间: " + DeskUtils.formatBytes(totalSpace));
     *
     * // 比较两种API的结果
     * long fileTotal = DeskUtils.getDiskTotalSpace("/");
     * long storeTotal = DeskUtils.getSpecificDiskTotalSpace("/");
     * System.out.println("File API总空间: " + DeskUtils.formatBytes(fileTotal));
     * System.out.println("FileStore API总空间: " + DeskUtils.formatBytes(storeTotal));
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>需要Java 7或更高版本</li>
     *   <li>在某些特殊文件系统上可能不可用</li>
     *   <li>性能比File API稍慢</li>
     *   <li>建议在需要精确度时使用</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #getDiskTotalSpace(String)} - 使用File API获取总空间</li>
     *   <li>{@link #getSpecificDiskUsableSpace(String)} - 获取可用空间</li>
     *   <li>{@link #getSpecificDiskUnallocatedSpace(String)} - 获取未分配空间</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @return 磁盘总空间（字节），如果获取失败返回-1
     *
     * @see java.nio.file.FileStore#getTotalSpace()
     * @see #getDiskTotalSpace(String)
     * @see #getSpecificDiskUsableSpace(String)
     */
    public static long getSpecificDiskTotalSpace(String path) {
        try {
            FileStore fs = getFileStore(path);
            return fs != null ? fs.getTotalSpace() : -1;
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 获取磁盘可用空间（考虑用户权限和配额）
     *
     * <h3>技术原理：</h3>
     * 使用 {@link java.nio.file.FileStore#getUsableSpace()} 方法获取当前用户实际可用的空间。
     * 这个值考虑了用户权限和磁盘配额限制，比空闲空间更准确。
     *
     * <h3>空间概念详解：</h3>
     * <ul>
     *   <li><strong>Usable Space</strong>：当前用户实际可用的空间</li>
     *   <li><strong>Permission Aware</strong>：考虑用户权限限制</li>
     *   <li><strong>Quota Aware</strong>：考虑磁盘配额限制</li>
     *   <li><strong>Realistic</strong>：反映用户实际可用空间</li>
     * </ul>
     *
     * <h3>与空闲空间的区别：</h3>
     * <ul>
     *   <li><strong>Free Space</strong>：文件系统中未被分配的空间，不考虑用户权限</li>
     *   <li><strong>Usable Space</strong>：当前用户实际可用的空间，考虑权限和配额</li>
     *   <li><strong>更准确</strong>：Usable Space更准确地反映用户实际可用空间</li>
     *   <li><strong>更安全</strong>：基于Usable Space的检查更安全</li>
     * </ul>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>精确空间检查</strong>：需要准确的空间信息</li>
     *   <li><strong>多用户环境</strong>：考虑用户权限和配额</li>
     *   <li><strong>安全操作</strong>：确保操作不会因权限问题失败</li>
     *   <li><strong>企业级应用</strong>：需要精确的空间管理</li>
     *   <li><strong>云环境</strong>：在云存储环境中使用</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 获取用户实际可用空间
     * long usableSpace = DeskUtils.getSpecificDiskUsableSpace("/");
     * System.out.println("实际可用空间: " + DeskUtils.formatBytes(usableSpace));
     *
     * // 安全的空间检查
     * long requiredSpace = 1024 * 1024 * 1024; // 1GB
     * if (usableSpace >= requiredSpace) {
     *     System.out.println("空间充足，可以安全操作");
     *     performSafeOperation();
     * } else {
     *     System.out.println("空间不足，需要清理或申请更多配额");
     * }
     *
     * // 在多用户环境中使用
     * long userSpace = DeskUtils.getSpecificDiskUsableSpace("/home/user1");
     * System.out.println("用户可用空间: " + DeskUtils.formatBytes(userSpace));
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>需要Java 7或更高版本</li>
     *   <li>在某些特殊文件系统上可能不可用</li>
     *   <li>结果可能因用户权限而异</li>
     *   <li>建议在关键操作前使用此方法</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #getDiskFreeSpace(String)} - 获取空闲空间</li>
     *   <li>{@link #getSpecificDiskTotalSpace(String)} - 获取总空间</li>
     *   <li>{@link #hasEnoughSpace(String, long)} - 检查空间是否充足</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @return 磁盘可用空间（字节），如果获取失败返回-1
     *
     * @see java.nio.file.FileStore#getUsableSpace()
     * @see #getDiskFreeSpace(String)
     * @see #getSpecificDiskTotalSpace(String)
     */
    public static long getSpecificDiskUsableSpace(String path) {
        try {
            FileStore fs = getFileStore(path);
            return fs != null ? fs.getUsableSpace() : -1;
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 获取磁盘未分配空间
     *
     * <h3>技术原理：</h3>
     * 使用 {@link java.nio.file.FileStore#getUnallocatedSpace()} 方法获取文件系统中
     * 未分配给任何文件的空间。这是NIO.2 API提供的精确空间信息。
     *
     * <h3>空间概念详解：</h3>
     * <ul>
     *   <li><strong>Unallocated Space</strong>：未分配给任何文件的空间</li>
     *   <li><strong>File System Level</strong>：文件系统层面的未分配空间</li>
     *   <li><strong>Physical Blocks</strong>：物理磁盘块级别的未分配空间</li>
     *   <li><strong>Not Reserved</strong>：不包括系统保留的空间</li>
     * </ul>
     *
     * <h3>与空闲空间的区别：</h3>
     * <table border="1">
     *   <tr><th>特性</th><th>Free Space</th><th>Unallocated Space</th></tr>
     *   <tr><td>定义</td><td>未被分配的空间</td><td>未分配给任何文件的空间</td></tr>
     *   <tr><td>计算方式</td><td>文件系统报告</td><td>精确计算</td></tr>
     *   <tr><td>精确度</td><td>基础精度</td><td>更高精度</td></tr>
     *   <tr><td>API</td><td>File API</td><td>FileStore API</td></tr>
     *   <tr><td>用途</td><td>一般空间检查</td><td>精确空间分析</td></tr>
     * </table>
     *
     * <h3>使用场景：</h3>
     * <ul>
     *   <li><strong>精确空间分析</strong>：需要准确的空间信息</li>
     *   <li><strong>存储规划</strong>：评估存储需求和容量</li>
     *   <li><strong>性能优化</strong>：分析磁盘碎片情况</li>
     *   <li><strong>企业级应用</strong>：需要精确的空间管理</li>
     *   <li><strong>云环境</strong>：在云存储环境中使用</li>
     *   <li><strong>虚拟化环境</strong>：在虚拟机中监控磁盘使用</li>
     * </ul>
     *
     * <h3>性能考虑：</h3>
     * <ul>
     *   <li>此操作比File API稍慢，但提供更准确的结果</li>
     *   <li>建议在需要精确度时使用，一般监控可使用File API</li>
     *   <li>对于频繁检查的场景，可以考虑缓存结果</li>
     *   <li>网络文件系统的检查可能较慢</li>
     * </ul>
     *
     * <h3>跨平台兼容性：</h3>
     * <ul>
     *   <li><strong>Windows</strong>：支持NTFS、FAT32等文件系统</li>
     *   <li><strong>Linux</strong>：支持ext4、xfs、btrfs等文件系统</li>
     *   <li><strong>macOS</strong>：支持APFS、HFS+等文件系统</li>
     *   <li><strong>网络文件系统</strong>：支持NFS、SMB等</li>
     * </ul>
     *
     * <h3>使用示例：</h3>
     * <pre>{@code
     * // 获取磁盘未分配空间
     * long unallocatedSpace = DeskUtils.getSpecificDiskUnallocatedSpace("/");
     * System.out.println("未分配空间: " + DeskUtils.formatBytes(unallocatedSpace));
     *
     * // 比较不同空间概念
     * long freeSpace = DeskUtils.getDiskFreeSpace("/");
     * long unallocatedSpace = DeskUtils.getSpecificDiskUnallocatedSpace("/");
     * System.out.println("空闲空间: " + DeskUtils.formatBytes(freeSpace));
     * System.out.println("未分配空间: " + DeskUtils.formatBytes(unallocatedSpace));
     *
     * // 分析磁盘碎片情况
     * long totalSpace = DeskUtils.getSpecificDiskTotalSpace("/");
     * long unallocatedSpace = DeskUtils.getSpecificDiskUnallocatedSpace("/");
     * double fragmentationRatio = (double) unallocatedSpace / totalSpace;
     * System.out.println("磁盘碎片率: " + (fragmentationRatio * 100) + "%");
     *
     * // 存储规划
     * long unallocatedSpace = DeskUtils.getSpecificDiskUnallocatedSpace("/data");
     * long requiredSpace = 1024 * 1024 * 1024 * 100; // 100GB
     * if (unallocatedSpace >= requiredSpace) {
     *     System.out.println("空间充足，可以安全部署");
     * } else {
     *     System.out.println("空间不足，需要扩容");
     * }
     * }</pre>
     *
     * <h3>注意事项：</h3>
     * <ul>
     *   <li>需要Java 7或更高版本</li>
     *   <li>在某些特殊文件系统上可能不可用</li>
     *   <li>结果可能与File API略有不同</li>
     *   <li>建议在关键应用中使用此方法</li>
     *   <li>网络文件系统的结果可能不准确</li>
     *   <li>某些文件系统可能有压缩或去重功能</li>
     * </ul>
     *
     * <h3>相关方法：</h3>
     * <ul>
     *   <li>{@link #getDiskFreeSpace(String)} - 获取空闲空间</li>
     *   <li>{@link #getSpecificDiskTotalSpace(String)} - 获取总空间</li>
     *   <li>{@link #getSpecificDiskUsableSpace(String)} - 获取可用空间</li>
     *   <li>{@link #getSpecificDiskUsagePercentage(String)} - 获取使用率</li>
     * </ul>
     *
     * <h3>技术细节：</h3>
     * <ul>
     *   <li>使用 {@link java.nio.file.FileStore#getUnallocatedSpace()} 获取未分配空间</li>
     *   <li>通过 {@link #getFileStore(String)} 获取FileStore对象</li>
     *   <li>如果FileStore为null，返回-1</li>
     *   <li>捕获所有异常并返回-1</li>
     * </ul>
     *
     * <h3>错误处理：</h3>
     * <ul>
     *   <li>如果获取FileStore失败，返回-1</li>
     *   <li>如果FileStore为null，返回-1</li>
     *   <li>捕获所有异常并返回-1</li>
     * </ul>
     *
     * <h3>应用场景详解：</h3>
     * <ul>
     *   <li><strong>存储管理</strong>：精确评估可用存储空间</li>
     *   <li><strong>容量规划</strong>：为未来存储需求做规划</li>
     *   <li><strong>性能分析</strong>：分析磁盘碎片对性能的影响</li>
     *   <li><strong>备份策略</strong>：评估备份空间需求</li>
     *   <li><strong>告警系统</strong>：设置精确的空间告警</li>
     * </ul>
     *
     * @param path 磁盘路径
     * @return 未分配空间（字节），如果获取失败返回-1
     *
     * @see java.nio.file.FileStore#getUnallocatedSpace()
     * @see #getDiskFreeSpace(String)
     * @see #getSpecificDiskTotalSpace(String)
     * @see #getSpecificDiskUsableSpace(String)
     */
    public static long getSpecificDiskUnallocatedSpace(String path) {
        try {
            FileStore store = getFileStore(path);
            return store != null ? store.getUnallocatedSpace() : -1;
        } catch (Exception e) {
            return -1;
        }
    }


    public static FileSystemProvider getFileSystemProvider(String path) {
        return Paths.get(path).getFileSystem().provider();
    }

    public static FileSystem getFileSystem(String path) {
        try {
            return Paths.get(path).getFileSystem();
        } catch (Exception e) {
            return null;
        }
    }

    public static FileStore getFileStore(String path) {
        try {
            Path p = Paths.get(path);
            return p.getFileSystem().provider().getFileStore(p);
        } catch (Exception e) {
            return null;
        }
    }

    public static String getFileSystemName(String path) {
        try {
            FileStore fs = getFileStore(path);
            return fs != null ? fs.name() : null;
        } catch (Exception e) {
            return null;
        }
    }

    public static String getFileSystemType(String path) {
        try {
            FileStore fs = getFileStore(path);
            return fs != null ? fs.type() : null;
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 格式化字节数为可读字符串
     *
     * @param bytes 字节数
     * @return 格式化后的字符串（如：1.5 GB）
     */
    public static String formatBytes(long bytes) {
        if (bytes < 0) {
            return "0 B";
        }

        String[] units = {"B", "KB", "MB", "GB", "TB", "PB"};
        int unitIndex = 0;
        double size = bytes;

        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }

        return String.format("%.2f %s", size, units[unitIndex]);
    }

    // ==================== 文件操作 ====================

    /**
     * 安全读取文件内容
     *
     * @param filePath 文件路径
     * @return 文件内容，如果读取失败返回null
     */
    public static String readFileContent(String filePath) {
        try {
            return new String(Files.readAllBytes(Paths.get(filePath)));
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 安全写入文件内容
     *
     * @param filePath 文件路径
     * @param content  文件内容
     * @return 是否写入成功
     */
    public static boolean writeFileContent(String filePath, String content) {
        try {
            Files.write(Paths.get(filePath), content.getBytes());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 安全追加文件内容
     *
     * @param filePath 文件路径
     * @param content  追加内容
     * @return 是否追加成功
     */
    public static boolean appendFileContent(String filePath, String content) {
        try {
            Files.write(Paths.get(filePath), content.getBytes(),
                    StandardOpenOption.APPEND, StandardOpenOption.CREATE);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 复制文件
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     * @return 是否复制成功
     */
    public static boolean copyFile(String sourcePath, String targetPath) {
        try {
            Files.copy(Paths.get(sourcePath), Paths.get(targetPath),
                    StandardCopyOption.REPLACE_EXISTING);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 移动文件
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     * @return 是否移动成功
     */
    public static boolean moveFile(String sourcePath, String targetPath) {
        try {
            Files.move(Paths.get(sourcePath), Paths.get(targetPath),
                    StandardCopyOption.REPLACE_EXISTING);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 删除文件
     *
     * @param filePath 文件路径
     * @return 是否删除成功
     */
    public static boolean deleteFile(String filePath) {
        try {
            return Files.deleteIfExists(Paths.get(filePath));
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean deleteFiles(List<String> filePaths) {
        boolean success = true;
        for (String filePath : filePaths) {
            try {
                if (!Files.deleteIfExists(Paths.get(filePath))) {
                    success = false;
                }
            } catch (IOException e) {
                success = false;
            }
        }
        return success;
    }

    /**
     * 获取文件的MIME类型
     */
    public static String getFileMimeType(String filePath) {
        try {
            Path path = Paths.get(filePath);
            return Files.probeContentType(path);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 检查文件是否为空
     */
    public static boolean isEmptyFile(String filePath) {
        try {
            return Files.size(Paths.get(filePath)) == 0;
        } catch (IOException e) {
            return true;
        }
    }

    /**
     * 获取文件大小
     *
     * @param filePath 文件路径
     * @return 文件大小（字节），如果文件不存在返回-1
     */
    public static long getFileSize(String filePath) {
        try {
            return Files.size(Paths.get(filePath));
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 获取文件最后修改时间
     *
     * @param filePath 文件路径
     * @return 最后修改时间，如果获取失败返回null
     */
    public static Date getFileLastModified(String filePath) {
        try {
            long time = Files.getLastModifiedTime(Paths.get(filePath)).toMillis();
            return new Date(time);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 创建文件硬链接
     */
    public static boolean createHardLink(String existingFile, String newLink) {
        try {
            Files.createLink(Paths.get(newLink), Paths.get(existingFile));
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    // ==================== 目录操作 ====================

    /**
     * 计算目录下的文件数量
     */
    public static long getFileCount(String dirPath) {
        try (Stream<Path> paths = Files.walk(Paths.get(dirPath))) {
            return paths
                    .filter(Files::isRegularFile)
                    .count();
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 获取目录下子目录数量
     */
    public static long getDirectoryCount(String dirPath) {
        try (Stream<Path> paths = Files.list(Paths.get(dirPath))) {
            return paths
                    .filter(Files::isDirectory)
                    .count();
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 清空目录内容但保留目录
     */
    public static boolean clearDirectory(String dirPath) {
        try {
            Files.walkFileTree(Paths.get(dirPath), new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    // 不删除根目录
                    if (!dir.equals(Paths.get(dirPath))) {
                        Files.delete(dir);
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 创建目录（包括父目录）
     *
     * @param dirPath 目录路径
     * @return 是否创建成功
     */
    public static boolean createDirectory(String dirPath) {
        try {
            Files.createDirectories(Paths.get(dirPath));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 删除目录及其内容
     *
     * @param dirPath 目录路径
     * @return 是否删除成功
     */
    public static boolean deleteDirectory(String dirPath) {
        try {
            Files.walkFileTree(Paths.get(dirPath), new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.delete(dir);
                    return FileVisitResult.CONTINUE;
                }
            });
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 复制目录
     *
     * @param sourcePath 源目录路径
     * @param targetPath 目标目录路径
     * @return 是否复制成功
     */
    public static boolean copyDirectory(String sourcePath, String targetPath) {
        try {
            Path source = Paths.get(sourcePath);
            Path target = Paths.get(targetPath);

            Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    Path targetDir = target.resolve(source.relativize(dir));
                    Files.createDirectories(targetDir);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Path targetFile = target.resolve(source.relativize(file));
                    Files.copy(file, targetFile, StandardCopyOption.REPLACE_EXISTING);
                    return FileVisitResult.CONTINUE;
                }
            });
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取目录大小
     *
     * @param dirPath 目录路径
     * @return 目录大小（字节），如果获取失败返回-1
     */
    public static long getDirectorySize(String dirPath) {
        try (Stream<Path> paths = Files.walk(Paths.get(dirPath))) {
            return paths
                    .filter(Files::isRegularFile)
                    .mapToLong(path -> {
                        try {
                            return Files.size(path);
                        } catch (IOException e) {
                            return 0;
                        }
                    })
                    .sum();
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 列出目录中的所有文件
     *
     * @param dirPath 目录路径
     * @return 文件路径列表
     */
    public static List<String> listFiles(String dirPath) {
        try (Stream<Path> stream = Files.list(Paths.get(dirPath))) {
            return stream
                    .filter(Files::isRegularFile)
                    .map(Path::toString)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    /**
     * 列出目录中的所有子目录
     *
     * @param dirPath 目录路径
     * @return 子目录路径列表
     */
    public static List<String> listDirectories(String dirPath) {
        try (Stream<Path> stream = Files.list(Paths.get(dirPath))) {
            return stream
                    .filter(Files::isDirectory)
                    .map(Path::toString)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    /**
     * 递归列出目录中的所有文件
     *
     * @param dirPath 目录路径
     * @return 所有文件路径列表
     */
    public static List<String> listAllFiles(String dirPath) {
        try (Stream<Path> paths = Files.walk(Paths.get(dirPath))) {
            return paths
                    .filter(Files::isRegularFile)
                    .map(Path::toString)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    public static List<String> listAllFiles(String dirPath, int maxDepth) {
        try (Stream<Path> paths = Files.walk(Paths.get(dirPath), maxDepth)) {
            return paths
                    .filter(Files::isRegularFile)
                    .map(Path::toString)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    // ==================== 文件搜索 ====================

    /**
     * 按文件名搜索文件
     *
     * @param dirPath  搜索目录
     * @param fileName 文件名（支持通配符）
     * @return 匹配的文件路径列表
     */
    public static List<String> searchFilesByName(String dirPath, String fileName) {
        try (Stream<Path> paths = Files.walk(Paths.get(dirPath))) {
            return paths
                    .filter(Files::isRegularFile)
                    .filter(path -> path.getFileName().toString().contains(fileName))
                    .map(Path::toString)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }


    /**
     * 按文件扩展名搜索文件
     *
     * @param dirPath   搜索目录
     * @param extension 文件扩展名（不包含点号）
     * @return 匹配的文件路径列表
     */
    public static List<String> searchFilesByExtension(String dirPath, String extension) {
        try (Stream<Path> paths = Files.walk(Paths.get(dirPath))) {
            return paths
                    .filter(Files::isRegularFile)
                    .map(Path::toString)
                    .filter(s -> s.toLowerCase().endsWith("." + extension.toLowerCase()))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    // ==================== 文件信息 ====================

    /**
     * 检查文件是否存在
     *
     * @param filePath 文件路径
     * @return 文件是否存在
     */
    public static boolean fileExists(String filePath) {
        return Files.exists(Paths.get(filePath));
    }

    /**
     * 检查是否为文件
     *
     * @param filePath 文件路径
     * @return 是否为文件
     */
    public static boolean isFile(String filePath) {
        return Files.isRegularFile(Paths.get(filePath));
    }

    public static boolean isSymbolicLink(String filePath) {
        return Files.isSymbolicLink(Paths.get(filePath));
    }

    public static boolean isHidden(String filePath) {
        try {
            return Files.isHidden(Paths.get(filePath));
        } catch (IOException e) {
            return false;
        }
    }

    public static boolean isReadable(String filePath) {
        return Files.isReadable(Paths.get(filePath));
    }

    public static boolean isWritable(String filePath) {
        return Files.isWritable(Paths.get(filePath));
    }

    public static boolean isExecutable(String filePath) {
        return Files.isExecutable(Paths.get(filePath));
    }

    public static boolean isRegularFile(String filePath) {
        return Files.isRegularFile(Paths.get(filePath));
    }


    /**
     * 检查是否为目录
     *
     * @param filePath 文件路径
     * @return 是否为目录
     */
    public static boolean isDirectory(String filePath) {
        return Files.isDirectory(Paths.get(filePath));
    }


    /**
     * 获取文件扩展名
     *
     * @param filePath 文件路径
     * @return 文件扩展名（不包含点号）
     */
    public static String getFileExtension(String filePath) {
        int lastDot = filePath.lastIndexOf('.');
        return lastDot > 0 ? filePath.substring(lastDot + 1) : "";
    }

    /**
     * 获取文件名（不包含路径）
     *
     * @param filePath 文件路径
     * @return 文件名
     */
    public static String getFileName(String filePath) {
        return Paths.get(filePath).getFileName().toString();
    }

    /**
     * 获取文件路径的父目录
     *
     * @param filePath 文件路径
     * @return 父目录路径
     */
    public static String getParentPath(String filePath) {
        Path parent = Paths.get(filePath).getParent();
        return parent != null ? parent.toString() : null;
    }

    /**
     * 合并路径
     *
     * @param paths 路径数组
     * @return 合并后的路径
     */
    public static String joinPath(String... paths) {
        return Paths.get("", paths).toString();
    }

    /**
     * 获取绝对路径
     *
     * @param path 路径
     * @return 绝对路径
     */
    public static String getAbsolutePath(String path) {
        try {
            return Paths.get(path).toAbsolutePath().toString();
        } catch (Exception e) {
            return path;
        }
    }

    /**
     * 规范化路径
     *
     * @param path 路径
     * @return 规范化后的路径
     */
    public static String normalizePath(String path) {
        try {
            return Paths.get(path).normalize().toString();
        } catch (Exception e) {
            return path;
        }
    }

    // TODO 待完善

    /**
     * 监控目录变化（简化版本）
     */
    public static WatchService createDirectoryWatcher(String dirPath) throws IOException {
        Path path = Paths.get(dirPath);
        WatchService watchService = FileSystems.getDefault().newWatchService();
        path.register(watchService,
                StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_DELETE,
                StandardWatchEventKinds.ENTRY_MODIFY);
        return watchService;
    }

    /**
     * 获取文件系统根目录
     */
    public static List<String> getRootDirectories() {
        try {
            return StreamSupport.stream(FileSystems.getDefault().getRootDirectories().spliterator(), false)
                    .map(Path::toString)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    /**
     * 生成文件校验和
     */
    public static String getFileChecksum(String filePath, String algorithm) throws NoSuchAlgorithmException, IOException {
        MessageDigest digest = MessageDigest.getInstance(algorithm);
        try (InputStream is = Files.newInputStream(Paths.get(filePath))) {
            byte[] buffer = new byte[8192];
            int read;
            while ((read = is.read(buffer)) > 0) {
                digest.update(buffer, 0, read);
            }
        }
        return Base64.getEncoder().encodeToString(digest.digest());
    }

    /**
     * 获取文件权限
     */
    public static Set<PosixFilePermission> getFilePermissions(String filePath) {
        try {
            return Files.getPosixFilePermissions(Paths.get(filePath));
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 设置文件权限
     */
    public static boolean setFilePermissions(String filePath, Set<PosixFilePermission> permissions) {
        try {
            Files.setPosixFilePermissions(Paths.get(filePath), permissions);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

}